home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / PCTERM.ASM < prev    next >
Assembly Source File  |  1990-02-11  |  18KB  |  571 lines

  1. ;--------------------------------------------------------------------
  2. ;                             DUMBTERM
  3. ;  Original author is CJ Dunford 09/12/83, modified by Jeff Firestone
  4. ;  on 01/15/84.  This program sets up the interrupt for COM1.  It uses
  5. ;  buffered communications.  The program is based upon PC Tech Journal
  6. ;  Jan '84, p144-186.
  7. ;---------------------------------------------------------------------
  8.  
  9. bufsize      equ     4096            ;4K Buffer
  10.  
  11. LF           equ     0Ah
  12. CR           equ     0Dh
  13. K_ESC          equ     1Bh
  14.  
  15. ; ------- BIOS calls
  16.  
  17. RS232        equ     14h            ;RS232 service
  18. kbd_io       equ     16h            ;Keyboard service
  19.  
  20. ; ------- INS8250 registers
  21.  
  22. THR          equ     3F8h           ;Trans holding register (write)
  23. RBR          equ     3F8h           ;Recieve buffer register (read)
  24. IER          equ     3F9h           ;Interrupt inable register
  25. LCR          equ     3FBh           ;Line control register
  26.                                     ;  Bit 7 of LCR is "DLAB". DLAB must
  27.                                     ;  be zero to access THR, RBR, IER.
  28. MCR         equ      3FCh           ;Modem control register
  29. LSR         equ      3FDh           ;Line status register
  30. MSR         equ      3FEh           ;Modem status register
  31.  
  32. ; ------- Comm parameter definition
  33. ; Refer to IBM Tech Ref manual page A-20
  34. ; See PROC INIT for usage.
  35. ; ---------------------------------------
  36. commparm   record baud:3, parity:2, stopbits:1, wordbits:2
  37.  
  38. ; Buad rates
  39. B110        equ      000b
  40. B150        equ      001b
  41. B300        equ      010b
  42. B600        equ      011b
  43. B1200       equ      100b
  44. B2400       equ      101b
  45. B4800       equ      110b
  46. B9600       equ      111b
  47.  
  48. ; Parity
  49. no_parity    equ     00b
  50. odd_parity   equ     01b
  51. even_parity  equ     11b
  52.  
  53. ; Stop bits
  54. stop1        equ     0
  55. stop2        equ     1
  56.  
  57. ; Data bits
  58. data7        equ     10b
  59. data8        equ     11b
  60.  
  61.  
  62. ;*****************************
  63. ;         MACROS
  64. ;*****************************
  65.  
  66. @bioscall MACRO call_num, parm
  67. ;; Generates an 'INT call_num', with parm in AH
  68.             IFNB     <parm>
  69.               mov    ah,parm
  70.             ENDIF
  71.             int      call_num
  72.             ENDM
  73.  
  74.  
  75. @doscall MACRO function, parm
  76. ;; Generates a DOS function call with parm in AH
  77.             IFNB     <parm>
  78.               mov    al,parm
  79.             ENDIF
  80.             @bioscall 21h,function
  81.             ENDM
  82.  
  83.  
  84. ;******************************
  85. ;    DATA & STACK SEGMENTS
  86. ;******************************
  87.  
  88. data segment para public 'data'
  89.  
  90. ; ----- The string section
  91. sgreeting      db      '--- ONLINE -0--',cr,lf,'$'
  92. sgoodbye       db      cr,lf,'--- OFFLINE ---',cr,lf,'$'
  93. serr1          db      '<R>$'          ;RS232 receive error
  94. serr2          db      '<S>$'          ;RS232 send error
  95. serr3          db      '<B>$'          ;Receive buffer overflow error
  96.  
  97. ; ----- Flags
  98. brcv_err       db     0                ;Nonzero on RS232 receive error
  99. boverflow      db     0                ;Nonzero on buffer overflow
  100. bdoneflag      db     0                ;Nonzero after ESC from kbd
  101.  
  102. ; ----- Receive data buffer and associated pointers
  103. ; >> Buffer is empty if head point4er = tail pointer
  104. wbufhead       dw     buffer           ;Pointer to head of buffer
  105. wbuftail       dw     buffer           ;Pointer to tail of buffer
  106. buffer         db     BUFSIZE dup (?)
  107. bufend         equ    $
  108. data ends
  109.  
  110. ; ----- Stack
  111. stack segment para stack 'stack'
  112.               db      256 dup (?)
  113. stack ends
  114.  
  115.  
  116. ;* * * * * * * * * * * * * * * * *
  117. ;         PROGRAM BODY
  118. ;* * * * * * * * * * * * * * * * *
  119.  
  120. code segment para public 'code'
  121.              assume cs:code, ds:data, ss:stack
  122.  
  123. main         proc     far
  124.  
  125. ; ------ Initialize
  126.              push     ds                ;Set up long return to DOS
  127.              sub      ax,ax
  128.              push     ax
  129.              call     init              ;Rest of initialization
  130.  
  131. ; ------ Main program loop
  132. M100:        call     buffer_check      ;Check RS232 buffer, display if char
  133.              call     kb_check          ;Check kbd, Send to RS232.
  134.              test     bdoneflag,0FFh    ;Non-zero if done
  135.              jz       M100              ;Loop till ESC received
  136.  
  137. ; ------ ESC received.  Clean up interrupt & exit
  138.              call     cleanup
  139.              ret                        ;Return to DOS
  140. main         endp
  141.  
  142. ;* * * * * * * * * * * * * * * * * * * *
  143. ;         PRIMARY BLOCKS
  144. ;* * * * * * * * * * * * * * * * * * * *
  145.  
  146. ; ------ Init ---------------------------------
  147. ;Program initialization
  148. ;  set up RS232
  149. ;  set up vector for RS232 interrupt (INT 0Ch)
  150. ;  Enable IRQ4
  151. ;  Enable RS232 interrupt on data ready
  152. ; --------------------------------------------
  153.  
  154. init         proc     near
  155.  
  156. ; ----- Initialize RS232 300,8,N,1
  157.              mov      dx,0
  158.              mov      al,commparm <B9600,even_Parity,stop1,data7>
  159.              @bioscall RS232,0
  160.  
  161. ; ----- Set up INT '0C' for IRQ4
  162.             cli                               ;Interrupts off during setup
  163.             push      ds                      ;Save DS
  164.             mov       dx,offset ISR           ;Point to RS232 ISR in DS:DX
  165.             push      cs
  166.             pop       ds
  167.             @doscall 25h,0Ch                  ;Set vector intr for IRQ4
  168.             pop       ds                      ;Restore DS
  169.  
  170. ; ------ Enable IRQ4 on 8259 interrupt controller
  171.             in        al,21h                  ;Get current mask
  172.             and       al,11101111b            ;Reset IRQ4 mask
  173.             out       21h,al                  ;restore to IMR
  174.  
  175. ; ------ Enable 8250 data ready interrupt
  176.             mov      dx,LCR                   ;DX <== LCR
  177.             in       al,dx                    ;reset DLAB for IER access
  178.             and      al,01111111b
  179.             out      dx,al
  180.             mov      dx,IER                   ;address IER
  181.             mov      al,00000001b             ;Enable data-ready interrupt
  182.             out      dx,al
  183.  
  184. ; ------ Enable OUT2 on 8250
  185.             mov      dx,MCR                   ;Address MCR
  186.             mov      al,00001000b             ;Enable OUT2
  187.             out      dx,al
  188.             sti
  189.  
  190. ; ------ Display greeting & return
  191.             mov      ax,data                  ;Establish data seg address
  192.             mov      ds,ax
  193.             mov      dx,offset sgreeting      ;Point to greeting
  194.             call     strdisp                  ;Display it
  195.             ret
  196. init endp
  197.  
  198. ; ------ Buffer Check ------------------
  199. ; RS232 buffer check
  200. ;
  201. ; This block checks the received data buffer.
  202. ; It functions as follows:
  203. ;
  204. ; If the RS232 input buffer is not empty
  205. ;   Get the first character
  206. ;   Display the character
  207. ;   Update buffer pointer
  208. ; If the RS232 receive error flag is nonzero
  209. ;   Display an error indicator
  210. ;
  211. ; Entry:
  212. ;   No requirement
  213. ; Exit
  214. ;   AX, BX, DX destroyed
  215. ; --------------------------------------
  216.  
  217.  
  218. buffer_check proc near
  219.  
  220. ; ------ Check buffer status
  221.           mov      bx,wbufhead               ;buffer head pointer
  222.           cmp      bx,wbuftail               ;buffer empty if head = tail
  223.           je       BC100
  224.  
  225. ; ------ Something in buffer--get 1st char, fix pointers
  226.           mov      al,[bx]                   ;get the char
  227.           call     incptr                    ;Bump buffer head pointer
  228.           mov      wbufhead,bx
  229.  
  230. ; ------ Display character received. Filter CR/LF
  231.           cmp    al,LF                       ;Is it a line feed
  232.           je     BC100                       ;Skip display if yes
  233.           call   chdisp                      ;Display if no
  234.           cmp    al,CR
  235.           jne    BC100
  236.           mov    al,LF
  237.           call   chdisp
  238.  
  239. ; ------ Test RS232 receive status; display errors
  240. BC100:    Test   brcv_err,0FFh               ;Flag nonzero if errors
  241.           jz     BC200                       ;Jump if no errors
  242.           mov    dx,offset serr1             ;Point to error msg
  243.           call   strdisp
  244.           mov    brcv_err,0                  ;Clear error flag
  245.  
  246. ; ----- Test for buffer overflow; display errors
  247. BC200:
  248.          test    boverflow, 0FFh
  249.          jz      BC300
  250.          mov     boverflow,0                 ;Clear the flag
  251.          mov     dx,offset serr3             ;Point to error msg
  252.          call    strdisp
  253.  
  254. BC300:   ret
  255. buffer_check endp
  256.  
  257. ; ----- KB_CHECK -----------------------------------
  258. ; Check the keyboard.  Functions as follows
  259. ;
  260. ; Check the keyboard status
  261. ; If a characteris available
  262. ;   If the character is ESC
  263. ;     set the done flag
  264. ;   ELSE
  265. ;     send it to RS232 and watch for errors
  266. ;
  267. ;  This routine does not echo the characters to the display.
  268. ;
  269. ; Entry:
  270. ;   No requirement
  271. ; Exit
  272. ;   AX, DX destroyed
  273. ; --------------------------------------
  274.  
  275. kb_check proc near
  276.  
  277. ; ----- Poll keyboard, check chars received
  278.          call    kb_poll                 ;Poll the keyboard
  279.          jz      KBC900                  ;Kbd clear, exit
  280.          cmp     al,K_ESC                  ;Escape?
  281.          jne     KBC100
  282.          mov     bdoneflag,0FFh          ;Yes, set terminate flag
  283.          jmp     short KBC900
  284.  
  285. ; ----- Send the received char, watch for errors
  286. KBC100:  Call    RS232_out               ;Send it
  287.          test    ah,80h                  ;Time out?
  288.          jz      KBC900
  289.          mov     dx,offset serr2         ;Point to error msg
  290.          call    strdisp                 ; and display
  291.  
  292. KBC900:  ret
  293. kb_check endp
  294.  
  295. ; ----- ISR ------------------------------------------------------
  296. ; This is the RS232 interrupt service routine.  It is entered
  297. ; whenever the RS232 port interrupts on a 'data ready'
  298. ; condition.  The routine simply reads the data from the asynch
  299. ; chip and stuffs it in the buffer.  Note that the process of reading
  300. ; the received data register in the 8250 clears IRQ4.  However, the
  301. ; 8259 must be told specifically that the interrupt service is complete.
  302. ;
  303. ; This replaces the function 2 of BIOS interrupt 14h (receive a character
  304. ; over the comm line).  Since it cannot return errors in a register, it
  305. ; puts the error marker in memory at 'brcv_err'.  The error flag is
  306. ; sticky -- a successful read will not clear a prior error indication.
  307. ; This allows the program mainline to examine the error status at its
  308. ; leisure.  Error bits are the same as in RS232OUT, above, except that
  309. ; ONLY the error bits are set, and bit 7 is not used (always 0).  In
  310. ; other words, brcv_err is nonzero only on an error.  Timeout errors
  311. ; are not possible here.
  312. ;
  313. ; The ISR will set the overflow flag if the buffer should overflow.
  314. ; This shouldn't happen.
  315. ; --------------------------------------------------------------------
  316.  
  317. ISR      proc   near
  318.          sti                      ;Allow other interrupts
  319.          push   ax                ;Save all regs used
  320.          push   bx
  321.          push   dx
  322.          push   si
  323.          push   ds
  324.  
  325. ; ---- Establish data addressability
  326.          mov    ax,data
  327.          mov    ds,ax
  328.  
  329. ; ---- Get error bits
  330.          mov    dx,LSR            ;Save address of RS232
  331.          in     al,dx             ;Get status
  332.          and    al,00011110b      ;Mask non-error bits
  333.          jz     ISR010            ;Skip error set if OK
  334.          mov    brcv_err,al       ;Set error indicator
  335.  
  336. ; ---- Get incoming character and buffer it
  337. ISR010:  mov    dx,RBR            ;Receive buffer
  338.          in     al,dx             ;Get input buffer
  339.          mov    bx,wbuftail       ;Buffer input pointer
  340.          mov    si,bx             ;Set pointer before increment
  341.          call   incptr            ;Bump input pointer
  342.          cmp    bx,wbufhead       ;Overflow if head = tail
  343.          je     ISR020            ;Overflow
  344.          mov    [si],al           ;No overflow, save char in buf
  345.          mov    wbuftail,bx       ;And new input pointer
  346.          jmp short ISR999
  347.  
  348. ISR020:  mov    boverflow, 0FFh   ;Set overflow flag
  349.  
  350. ; ---- Signal end of interrupt to 8259
  351. ISR999:  cli
  352.          mov    al,20h            ;Non-specific EOI
  353.          out    20h,al            ;Send it
  354.  
  355. ; ---- Restore regs & return.  IRET reenables interrupts
  356.          pop    ds
  357.          pop    si
  358.          pop    dx
  359.          pop    bx
  360.          pop    ax
  361.          iret
  362. ISR endp
  363.  
  364. ; ---- CLEANUP --------------------
  365. ; End of program housekeeping
  366. ;   -- Disable IRQ4
  367. ;   -- Disable 8250 interrupts
  368. ;   -- Disable OUT2
  369. ;   -- Display offline message
  370. ; ---------------------------------
  371.  
  372. cleanup proc near
  373.  
  374. ; ---- Disable IRQ4 on 8259
  375.          cli
  376.          in      al,21h                ;IMR
  377.          or      al,00010000b          ;Mask bit 4 -- IRQ4
  378.          out     21h,al
  379.  
  380. ; ---- Disable 8250 data ready interrupt
  381.          mov     dx, LCR               ;DX <=== LCR
  382.          in      al,dx                 ;Reset DLAB for IER access
  383.          and     al,01111111b
  384.          out     dx,al
  385.          mov     dx,IER                ;Address IER
  386.          mov     al,0                  ;Disable all 8250 interrupts
  387.          out     dx,al
  388.  
  389. ; ---- Disable OUT2 on 8250
  390.        mov      dx,MCR                ;Address MCR
  391.        mov      al,0                  ;Disable OUT2
  392.        out      dx,al
  393.        sti
  394.  
  395. ; ---- Display bye-bye
  396.        mov     dx,offset  sgoodbye
  397.        call    strdisp
  398. cleanup endp
  399.  
  400.  
  401. ; * * * * * * * * * * * * * *
  402. ;   I/O & General Subroutines
  403. ; * * * * * * * * * * * * * *
  404.  
  405. ; ---- KB_POLL ------------------------------
  406. ; Set/reset Z flag on keyboard buffer status.
  407. ;
  408. ; Entry:
  409. ;   No requirements
  410. ; Exit:
  411. ;   Z = 1 if nothing available
  412. ;   Z = 0 if char available from kbd
  413. ;   IF Z = 0
  414. ;     AL = char
  415. ;     AH = scan code
  416. ;   Other regs preserved
  417. ; ---------------------------------------------
  418.  
  419. kb_poll proc near
  420.         @bioscall  kbd_io,1             ;Poll KB. Sets Z flag if KB bfr empty
  421.         jz         KB999                ;Nothing there
  422.         pushf                           ;Save flag status
  423.         @bioscall  kbd_io,0             ;Something there; get it
  424.         popf
  425. KB999:
  426.         ret
  427. kb_poll endp
  428.  
  429. ; -- RS232_OUT ----------------------------------------
  430. ; RS232 output routine
  431. ;
  432. ; This routine sends one character to the RS232 port.
  433. ; It replaces function 1 of BIOS int 14K.  This is
  434. ; necessary because BIOS will disable the RS232
  435. ; interrupt (by disabling OUT2) every time it is
  436. ; called.
  437. ;
  438. ; Entry:
  439. ;   AL = character to be transmitted
  440. ; Exit:
  441. ;   AH = send status
  442. ;     Bit 7 = 1 if RS232 timeout occurred
  443. ;     If bit 7 = 0
  444. ;       bit 6: trans shift register empty
  445. ;       bit 5: trans holding register empty
  446. ;       bit 4: break detect
  447. ;       bit 3: framing error
  448. ;       bit 2: parity error
  449. ;       bit 1: overrun error
  450. ;       bit 0: data ready
  451. ;  Other regs preserved.
  452. ; -------------------------------------------------------
  453.  
  454. RS232_out proc near
  455.           push   bx             ;Save regs used
  456.           push   cs
  457.           push   dx
  458.  
  459. ; ----- Set up RS232
  460.           mov    bl,al          ;Save char to bl temporarily
  461.           mov    dx,MCR         ;Modem Control Register
  462.           mov    al,00001011b   ; OUT2, DTR, RTS
  463.           out    dx,al
  464.           sub    cx,cx          ;Initialize timeout count
  465.           mov    dx,MSR         ;Modem Status Register
  466.  
  467. ; ----- Wait for DSR
  468. RS100:
  469.           in     al,dx
  470.           test   al,20h         ;Data set ready?
  471.           jnz    RS150          ;Yes
  472.           loop   RS100          ;No, retry till timeout
  473.           mov    ah,80h         ;Set timeout
  474.           jmp    short RSXIT    ;and quit
  475.  
  476. ; ----- Wait for CTS
  477. RS150:
  478.           sub    cx,cx          ;Another timeout count
  479. RS200:
  480.           in     al,dx
  481.           test   al,10h         ;Clear to send?
  482.           jnz    RS250          ;Yes
  483.           loop   RS200          ;No, loop till timeout
  484.           mov    ah,80h         ;TImeout,set flag
  485.           jmp short RSXIT       ;And quit
  486.  
  487. ; ----- Wait for THRE
  488. RS250:
  489.           mov    dx,LSR         ;Line Status Register
  490.           sub    cx,cx          ;Yes another timeout count
  491. RS300:
  492.           in     al,dx          ;LSR status
  493.           test   al,20h         ;Transmit holding reg empty?
  494.           jnz    RS350          ;Yes
  495.           loop   RS300          ;No, loop till timeout
  496.           mov    ah,80h         ;Timeout, set flag
  497.           jmp short RSXIT
  498.  
  499. ; ------ Get line status, send char
  500. RS350:
  501.           mov    ah,al          ;Get line status for return
  502.           and    ah,01111111b   ;Mask out bit 7
  503.           mov    al,bl          ;Restore char to AL
  504.           mov    dx,THR         ;Transmit holding register
  505.           out    dx,al          ;Output it to RS232
  506. RSXIT:
  507.           pop    dx
  508.           pop    cx
  509.           pop    bx
  510.           ret
  511. RS232_out endp
  512.  
  513.  
  514. ; ---- CHDISP ----------------------------------
  515. ; Display the character in AL on the CRT
  516. ; Entry:
  517. ;   AL = char
  518. ; Exit:
  519. ;   All regs restored
  520. ; ----------------------------------------------
  521.  
  522. chdisp proc near
  523.        push   ax
  524.        push   dx
  525.        mov    dl,al
  526.        @doscall 2
  527.        pop    dx
  528.        pop    ax
  529.        ret
  530. chdisp endp
  531.  
  532.  
  533. ; ---- STRDISP ----------------------------
  534. ; Display the string at DS:DX on the CRT
  535. ; Entry:
  536. ;   DS:DX ==> string
  537. ; Exit:
  538. ;   All regs restored
  539. ; -----------------------------------------
  540.  
  541. strdisp proc near
  542.         push      ax
  543.         @doscall 9
  544.         pop       ax
  545.         ret
  546. strdisp endp
  547.  
  548.  
  549. ; ----- INCPTR ------------------------------
  550. ; Increments the buffer pointer in reg BX.
  551. ; If the pointer goes beyond the end of the
  552. ; buffer, wrap around to start.
  553. ;
  554. ; Entry:
  555. ;   BX = buffer pointer
  556. ; Exit
  557. ;   BX = advanced buffer pointer
  558. ;   Other regs restored
  559. ; --------------------------------------------
  560.  
  561. incptr proc near
  562.        inc     bx                            ; Bump pointer
  563.        cmp     bx,offset bufend              ; Past end?
  564.        jne     IP100                         ; Jump if not
  565.        mov     bx,offset buffer              ; Else point to start
  566. IP100:
  567.        ret
  568. incptr endp
  569. code   ends
  570.        end  main
  571.